import { v4 as uuidv4 } from 'uuid'
import EventEmit from '../event/eventEmit'
import { coordinateUtils, isVisibleByBounds } from '../utils/index.js'
/**
 * 添加弹窗
 */
class Popup extends EventEmit {
  constructor(viewer, options = {}) {
    super()
    this.element = null // 弹窗dom元素
    this.viewer = viewer
    this.options = options
    this._renderListener = null // 监听postRender
    initPopup.call(this, options)
    this.eventHandler = null
    addMapEvent.call(this)
    addCameraEvent.call(this)
    // addMoseMoveEvent.call(this)
  }
  /**
   * 自定义事事件回调
   * @param {String} type 事件类型
   * @param {Function} callback 回调函数
   */
  on (type, callback) {
    if (typeof callback !== 'function') return
    if (!this._eventList) {
      this._eventList = {}
    }
    this._eventList[type] = callback
    this.listen(type, callback)
  }
  /**
   * 设置弹窗位置
   * @param {*} position 
   */
  setPosition (position) {
    this.options.position = position
    const { popPosition, offset } = this.options
    const [offsetX = 0, offsetY = 0] = offset || []

    // clientWidth 元素内容区宽度+内边距
    const { clientWidth, clientHeight } = this.element
    const screenPos = coordinateUtils.lnglatToCartesian2.call(this, position)
    if (!screenPos || !this.element) { return this }
    let left = screenPos.x - clientWidth / 2 + offsetX
    let top = screenPos.y - clientHeight + offsetY
    // let left = screenPos.x - this.element.offsetWidth / 2 + offsetX
    // let top = screenPos.y - this.element.offsetHeight + offsetY
    if (popPosition) {
      if (popPosition === "left-bottom") {
        left = screenPos.x
        top = screenPos.y - clientHeight
      } else if (popPosition === "left-center") {
        left = screenPos.x + 20
        top = screenPos.y - clientHeight / 2
      }
    }
    this.element.style.position = "absolute"
    this.element.style.display = "block"
    this.element.style.left = `${left}px`
    this.element.style.top = `${top}px`
    return this
  }
  /**
   * 设置弹窗内容
   * @param {*} innerHTML html内容
   * @param {*} isInit 是否是初始化
   */
  setContent (innerHTML, isInit = false) {
    this.element && (this.element.innerHTML = innerHTML)
    this.options.html = innerHTML
    return this
  }
  /**
   * 设置弹窗显示
   */
  show () {
    if (this.element) {
      this.element.style.visibility = "visible"
    }
  }
  /**
   * 设置弹窗隐藏
   */
  hide () {
    if (this.element) {
      this.element.style.visibility = "hidden"
    }
  }
  /**
   * 移除弹窗
   */
  remove () {
    if (this.element) {
      this.element.remove()
      this.element = null
    }
    this.eventHandler && this.eventHandler.destroy()
    if (this._cameraMoveEnd) {
      this.viewer.camera.moveEnd.removeEventListener(this._cameraMoveEnd)
    }
    if (this._renderListener) {
      this._renderListener()
      this._renderListener = undefined
    }
  }
}
/**
 * 初始化弹窗
 * @param {Viewer} viewer Viewer实例
 * @param {*} options 
 */
function initPopup (options) {
  const { id, position, innerHTML } = options
  options.id = id || uuidv4()
  const popDom = document.getElementById(options.id)
  if (popDom) {
    throw new Error(`id为${id}的弹层dom元素已存在！`)
  }
  const element = createPopupDom.call(this, options)
  this.element = element
  innerHTML && this.setContent(innerHTML, true)
  position && this.setPosition(position)
}
/**
 * @description
 * @param {*} options 
 * @returns 
 */
function createPopupDom (options) {
  const { id, className = 'popup-container' } = options
  if (this.viewer) {
    const container = this.viewer.container
    const popupContainer = document.createElement("div")
    popupContainer.id = id
    popupContainer.className = className
    container.appendChild(popupContainer)
    return popupContainer
  }
}
/**
 * 地图添加监听，用于更新弹窗的位置
 */
function addMapEvent () {
  const that = this
  function render () {
    const { position, renderInViewBounds } = that.options
    const visible = isVisibleByBounds.call(that, position)
    if (renderInViewBounds) {
      if (visible) {
        that.show()
      } else {
        that.hide()
      }
    } else {
      that.setPosition(position)
    }
  }
  this._renderListener = this.viewer.scene.postRender.addEventListener(render)
}
/**
 * 添加相机事件，用于控制弹窗的显示和隐藏
 */
function addCameraEvent () {
  const { maxVisibleHeight } = this.options
  const that = this
  function _cameraMoveEnd () {
    const h = that.viewer.camera.getMagnitude()
    const min = 6375000
    if (h && maxVisibleHeight && this.element) {
      if (h - min > maxVisibleHeight) {
        this.hide()
      } else {
        this.show()
      }
    }
  }

  Object.defineProperty(this, '_cameraMoveEnd', { value: _cameraMoveEnd.bind(this) })
  this.viewer.camera.moveEnd.addEventListener(_cameraMoveEnd)
}

export default Popup